package io.github.talelin.latticy.controller.v1;


import io.github.talelin.core.annotation.LoginRequired;
import io.github.talelin.core.annotation.PermissionMeta;
import io.github.talelin.core.annotation.PermissionModule;
import io.github.talelin.latticy.bo.OrderVO;
import io.github.talelin.latticy.bo.OrderVO2;
import io.github.talelin.latticy.common.LocalUser;
import io.github.talelin.latticy.common.configuration.FreeMarkerConfig;
import io.github.talelin.latticy.common.configuration.KieConfig;
import io.github.talelin.latticy.common.configuration.MyKieContext;
import io.github.talelin.latticy.dto.drools.BookCalculateDTO;
import io.github.talelin.latticy.filter.CustomAgendaFilter;
import io.github.talelin.latticy.model.ChargeDataItemDO;
import io.github.talelin.latticy.model.FeeDetailDO;
import io.github.talelin.latticy.model.RulesDO;
import io.github.talelin.latticy.model.UserDO;
import io.github.talelin.latticy.service.AccuracyService;
import io.github.talelin.latticy.service.ChargeDataItemService;
import io.github.talelin.latticy.service.RulesService;
import io.github.talelin.latticy.service.UserService;
import io.github.talelin.latticy.service.impl.AccuracyServiceImpl;
import io.github.talelin.latticy.vo.UpdatedVO;
import io.seata.core.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.drools.core.base.RuleNameEqualsAgendaFilter;
import org.drools.core.base.RuleNameStartsWithAgendaFilter;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @authoer:wulongbo
 * @createDate:2022/8/8
 * @description: 重新加载规则
 */

@Slf4j
@RestController
@RequestMapping("/kieReloading")
@Validated
@PermissionModule(value = "规则引擎")
public class KieReloadingController {

    @Autowired
    MyKieContext myKieContext;

    @Autowired
    RulesService rulesService;

    @Autowired
    KieConfig kieConfig;

    @Autowired
    private FreeMarkerConfig freeMarkerConfig;

    @Autowired
    private AccuracyService accuracyService;

    @Autowired
    private ChargeDataItemService chargeDataItemService;

    /**
     * 重新加载规则
     *
     * @return
     */
    @RequestMapping("/reloading")
    public Result reloading() {
        try {
            KieContainer kieContainer = kieConfig.kieContainer();
            myKieContext.update(kieContainer);
            return Result.ok();
        } catch (Exception e) {
            log.error("重载kie异常,异常为:{}", e.getMessage());
            return Result.build("重新加载规则失败");
        }
    }

    /**
     * 图书优惠计算
     *
     * @return
     */
    @RequestMapping("/calculate")
    public UpdatedVO calculate(Double originalPrice) {
        // 获得Kie容器对象
//        KieContainer kieContainer = kieConfig.kieContainer();
        //会话对象，用于和规则引擎交互
        KieSession kieSession = myKieContext.getKieSession();
        //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
        OrderVO order = new OrderVO();
        order.setOriginalPrice(originalPrice);
        //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
        kieSession.insert(order);
        //激活规则引擎，如果规则匹配成功则执行规则
        kieSession.fireAllRules();
        System.out.println("优惠前原始价格：" + order.getOriginalPrice() +
                "，优惠后价格：" + order.getRealPrice());
        myKieContext.clean();
        return new UpdatedVO();
    }

    /**
     * 图书优惠计算
     *
     * @return
     */
    @GetMapping("/calculate2")
    public UpdatedVO calculateBookDiscount2And3(Double originalPrice) {
        //会话对象，用于和规则引擎交互
        KieSession kieSession = myKieContext.getKieSession();
        //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
        OrderVO order = new OrderVO();
        order.setOriginalPrice(originalPrice);
        //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
        kieSession.insert(order);
        //通过规则过滤器实现只执行指定规则
        Set set = new HashSet();
        set.add("book_discount_2");
        set.add("book_discount_3");
        kieSession.fireAllRules(new CustomAgendaFilter(set));
        System.out.println("优惠前原始价格：" + order.getOriginalPrice() +
                "，优惠后价格：" + order.getRealPrice());
        return new UpdatedVO();
    }

    /**
     * 图书优惠计算
     *
     * @return
     */
    @PostMapping("")
    @LoginRequired
    @PermissionMeta(value = "图书优惠计算引擎")
    public UpdatedVO calculateBookDiscount2And3(@Validated @RequestBody BookCalculateDTO dto) {
        //会话对象，用于和规则引擎交互
        KieSession kieSession = myKieContext.getKieSession();
        //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
        OrderVO order = new OrderVO();
        order.setOriginalPrice(dto.getOriginalPrice());
        //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
        myKieContext.insert(order);
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_".concat(String.valueOf(dto.getUserId()))));
        System.out.println("优惠前原始价格：" + order.getOriginalPrice() +
                "，优惠后价格：" + order.getRealPrice());
        return new UpdatedVO();
    }

    /**
     * 测试生成规则
     *
     * @param map
     */
    @PostMapping("/genaralRule")
    @LoginRequired
    public void generalRule(@Validated @RequestBody Map map) {
        UserDO user = LocalUser.getLocalUser();
        try {
            map.put("userId", user.getId());
            String rule = freeMarkerConfig.getContent("order.ftl", map);
            System.out.println(rule);
            RulesDO rulesDO = new RulesDO();
            rulesDO.setRule(rule);
            rulesDO.setName(map.get("ruleName").toString());
            rulesService.save(rulesDO);
            KieContainer kieContainer = kieConfig.kieContainer();
            myKieContext.update(kieContainer);
        } catch (Exception e) {
            log.error("重载kie异常,异常为:{}", e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 测试生成规则计算
     *
     * @return
     */
    @PostMapping("/generalRuleCal")
    @LoginRequired
    @PermissionMeta(value = "测试生成规则计算")
    public UpdatedVO generalRuleCal() {
        UserDO user = LocalUser.getLocalUser();
        //会话对象，用于和规则引擎交互
        KieSession kieSession = myKieContext.getKieSession();
        //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
        OrderVO2 order = new OrderVO2();
        order.setTransportationType(2);
        order.setOriginalPrice(10D);
        order.setSkuTypeQuantity(10);
        order.setBoxTotalNum(20);
//        order.setOriginalPrice(dto.getOriginalPrice());
        //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
        myKieContext.insert(order);
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule_".concat(String.valueOf(user.getId())).concat("_abcde")));
        System.out.println("优惠前原始价格：" + order.getOriginalPrice() +
                "，优惠后价格：" + order.getRealPrice());
        return new UpdatedVO();
    }

    /**
     * 测试生成规则计算2
     *
     * @return
     */
    @PostMapping("/generalRuleCal2")
    @LoginRequired
    @PermissionMeta(value = "测试生成规则计算2")
    public UpdatedVO generalRuleCal2() {
        UserDO user = LocalUser.getLocalUser();
        //会话对象，用于和规则引擎交互
        KieSession kieSession = myKieContext.getKieSession();
        //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
        kieSession.setGlobal("accuracyService", accuracyService);
        OrderVO2 order = new OrderVO2();
        order.setTransportationType(2);
        order.setOriginalPrice(10D);
        order.setSkuTypeQuantity(1000);
        order.setBoxTotalNum(8);
//        order.setOriginalPrice(dto.getOriginalPrice());
        //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
        myKieContext.insert(order);
        kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule_".concat(String.valueOf(user.getId())).concat("_aaaaaa")));
        System.out.println("优惠前原始价格：" + order.getOriginalPrice() +
                "，优惠后价格：" + order.getRealPrice());
        return new UpdatedVO();
    }


    /**
     * 入库规则xxx计算
     *
     * @return
     */
    @RequestMapping("/inboundCalculate")
    public UpdatedVO inboundCalculate() {
        try {
            //会话对象，用于和规则引擎交互
            KieSession kieSession = myKieContext.getKieSession();
            //构造订单对象，设置原始价格，由规则引擎根据优惠规则计算优惠后的价格
            ChargeDataItemDO chargeDataItemDO = chargeDataItemService.getById(1);
            kieSession.setGlobal("accuracyService", accuracyService);
            FeeDetailDO fee = new FeeDetailDO();
            kieSession.setGlobal("fee", fee);
            BigDecimal ruleCost = new BigDecimal(BigInteger.ZERO);
            kieSession.setGlobal("ruleCost", ruleCost);
            //将数据提供给规则引擎，规则引擎会根据提供的数据进行规则匹配
            kieSession.insert(chargeDataItemDO);
            //激活规则引擎，如果规则匹配成功则执行规则
            kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("我的第2个计费项"));
            System.out.println(fee.toString());
            myKieContext.clean();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new UpdatedVO();
    }
}
